package buaa.paas.kubectl;

import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.models.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

@Service
public class DeploymentUtil {
    @Autowired
    ApiUtil util;
    /**
     * 创建给一个项目创建一个Deployment
     * @param countReplica 复制的数量
     * @param imageName 镜像的名字
     * @param deploymentName deployment的名字
     * @param namespace 这个deployment的namespace，由项目名称和用户名完成
     * @param labels 这个的deployment的matchLabel
     * @param ports 被运行的容器的port
     * */
    public void createDeployment(int countReplica, String imageName, String deploymentName, String namespace, Map<Integer, String> ports, Map<String, String>labels) throws ApiException {
        V1DeploymentBuilder builder = new V1DeploymentBuilder();// 创建deployment的类
        List<V1ContainerPort> containerPorts = new LinkedList<>();
        for(int p: ports.keySet()){
            containerPorts.add(new V1ContainerPortBuilder().withContainerPort(p).withProtocol(ports.get(p)).build());
        }
        builder.withApiVersion("apps/v1");
        builder.withKind("Deployment");
        builder.withNewMetadata()
                .withName(deploymentName)
                .withNamespace(namespace)
                .endMetadata();
        builder.withNewSpec()
                .withReplicas(countReplica)
                .withNewSelector()
                    .withMatchLabels(labels)
                    .endSelector()
                .withNewTemplate()
                    .withNewMetadata()
                    .withLabels(labels)
                    .endMetadata()
                    .withNewSpec()
                    .withContainers().addNewContainer()
                    .withName(imageName)
                    .withImage(imageName)
                    .withPorts(containerPorts).endContainer().endSpec().endTemplate().endSpec();
        V1Deployment deployment = builder.build();
        util.getApi().createNamespacedDeployment(namespace, deployment, "true", null, null);
    }

    /**
     * 根据一个deployment，展示其相关信息
     * @param d 被了解的deployment
     * @return 这个deployment相关的信息，包括deployment的名字，准备好的数量，selectors
     * */
    public static TreeMap<String, Object> briefDeployment(V1Deployment d){
        TreeMap<String, Object> result = new TreeMap<>();
        result.put("Name", d.getMetadata().getName());
        result.put("CountReady", d.getStatus().getAvailableReplicas());
        result.put("CountDesired", d.getStatus().getReplicas());
        result.put("CountUpdated", d.getStatus().getUpdatedReplicas());
        result.put("Selectors", d.getSpec().getSelector().getMatchLabels());
        return result;
    }

    /**
     * 列出一个namespace中全部的deployment
     * @param namespace 目标的namespace
     * */
    public List<TreeMap<String, Object>> listDeployment(String namespace) throws ApiException {
        V1DeploymentList dList = util.getApi().listNamespacedDeployment(namespace, null, null, null, null, null, null, null, null, null);
        LinkedList<TreeMap<String, Object>> result = new LinkedList<>();
        for(V1Deployment d: dList.getItems()){
            result.addLast(briefDeployment(d));
        }
        return result;
    }

    /**
     * 获取一个deployment的具体信息
     * @param d 被描述的deployment的对象
     * @return 被描述的deployment的具体信息，在brief的基础上增加selector
     * */
    public static TreeMap<String, Object> describeDeployment(V1Deployment d){
        TreeMap<String, Object> result = briefDeployment(d);
        V1Container container = d.getSpec().getTemplate().getSpec().getContainers().get(0);
        TreeMap<String, Object> containerInfo = new TreeMap<>();
        containerInfo.put("Image", container.getImage());
        TreeMap<String, String> envs = new TreeMap<>();
        if(container.getEnv()!=null){
            for(V1EnvVar v: container.getEnv()){
                envs.put(v.getName(), v.getValue());
            }
            containerInfo.put("Envs", envs);
        }else{
            containerInfo.put("Envs", new TreeMap<>());
        }
        TreeMap<String, Object> ports = new TreeMap<>();
        if(container.getPorts() != null){
            for(V1ContainerPort p: container.getPorts()){
                ports.put(p.getProtocol(), p.getContainerPort());
            }
            containerInfo.put("Ports", ports);
        }else{
            containerInfo.put("Ports", new TreeMap<>());
        }
        result.put("Container", containerInfo);
        return result;
    }

    public V1Deployment findDeployment(String namespace, String name) throws ApiException {
        V1DeploymentList dList = util.getApi().listNamespacedDeployment(namespace, null, null, null, null, null, null, null, null, null);
        for(V1Deployment d:dList.getItems()){
            if(d.getMetadata().getName().compareTo(name) == 0){
                return d;
            }
        }
        return null;
    }
}
